package com.platform.comm.util;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * Operation utilities for File/Path, Stream etc
 */
public abstract class IOUtil {

    private IOUtil() {
        throw new IllegalStateException("Utility class");
    }

    private static final Logger LOGGER = LogManager.getLogger(IOUtil.class);

    /**
     * 创建指定路径的各级父目录（如果尚不存在的话）
     *
     * @return 指定路径的父目录
     * @throws IOException 如果出现I/O异常
     */
    public static Path createParentDirectories(Path path) throws IOException {
        final Path parent = path.getParent();
        if (parent.toFile().exists()) {
            return parent;
        }
        LOGGER.debug("Create parent directories... {}", parent);
        return Files.createDirectories(parent);
    }

    /**
     * 创建指定File对象的各级父目录（如果不存在的话）
     */
    public static boolean createParentDirs(File f) {
        final File parent = f.getParentFile();
        return parent.exists() || parent.mkdirs();
    }

    /**
     * 将输入流中的所有字节复制到指定文件中。<br>
     * 如果指定的目标路径还有所需的父目录尚未创建，则会一一创建所需的父目录
     *
     * @param in     源输入流。本方法保证在调用结束前关闭该流
     * @param target 目标文件路径。
     * @throws IOException 无法正常创建目标文件的所有父目录，或读写发生I/O异常时扔出
     */
    public static void copy(InputStream in, Path target, CopyOption... options) throws IOException {
        LOGGER.debug("Copy stream bytes to {}...", target);
        try {
            createParentDirectories(target);
            Files.copy(in, target, options);
        } finally {
            close(in);
        }
    }

    /**
     * 移动指定位置的文件到新位置。<br>
     * 如果目标位置的父级目录尚不存在，则创建所有必要的父目录
     *
     * @throws IOException 创建父目录或移动文件出现I/O异常
     */
    public static void move(Path source, Path target) throws IOException {
        LOGGER.debug("Move {} to {} ...", source, target);
        createParentDirectories(target);
        Files.move(source, target);
    }

    /**
     * 关闭指定的{@link Closeable}实例，忽略关闭时的I/O异常
     */
    public static void close(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                LOGGER.error("Close closeable instance error", e);
            }
        }
    }
}
